package ebj.common.google_code.guava;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import junit.framework.Assert;

import org.junit.Test;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.mysql.jdbc.PreparedStatement;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

public class CacheDemo {

	@Test
	public void demo() {
		// TODO Auto-generated method stub

		Cache<String, Obj> cache = CacheBuilder.newBuilder().maximumSize(2)
				.build();
		Obj obj_a = new Obj(1, 2);
		Obj obj_b = new Obj(2, 2);
		Obj obj_c = new Obj(3, 2);

		// first put count=1
		cache.put("a", obj_a);
		Assert.assertEquals(obj_a, cache.getIfPresent("a"));

		// 2nd put count=2
		cache.put("b", obj_b);

		// use a more than b
		cache.getIfPresent("a");
		Assert.assertEquals(obj_b, cache.getIfPresent("b"));
		Assert.assertEquals(obj_a, cache.getIfPresent("a"));

		// 3rd put count=3 need remove one
		cache.put("c", obj_c);
		Assert.assertEquals(obj_c, cache.getIfPresent("c"));
		Assert.assertTrue(cache.getIfPresent("b") == null);
	}

	@Test
	public void demo2() throws ExecutionException {
		// Cache<String, Obj> cache = CacheBuilder
		// .newBuilder()
		// .maximumSize(2)
		// .build();

		Obj obj_a = new Obj(1, 2);
		Obj obj_b = new Obj(2, 2);
		Obj obj_c = new Obj(3, 2);

		LoadingCache<String, Obj> cache = CacheBuilder.newBuilder().build(
				new CacheLoader<String, Obj>() {
					@Override
					public Obj load(String key) throws Exception {
						return new Obj(3, 3);
					}
				});
		Obj obj_d = new Obj(3, 3);

		// get method is the same as get(key,new Callable)
		Assert.assertEquals(obj_a, cache.get("d"));

		Assert.assertEquals(obj_a, cache.getIfPresent("d"));// 从cache重直接取
	}

	@Test
	public void loadServiceUrlTest() throws SQLException, ExecutionException, InterruptedException {
		
		LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
				.expireAfterAccess(3L, TimeUnit.SECONDS)// 3秒钟没有访问，则缓存失效
				.refreshAfterWrite(2L, TimeUnit.SECONDS) // 2秒钟后自动刷新
				//设置并发级别为8，允许同时最多8个线程并发修改
                .concurrencyLevel(8)
                // 设置写缓存后8秒钟过期
                // .expireAfterWrite(8, TimeUnit.SECONDS)
                //设置缓存容器的初始容量为10
                .initialCapacity(10)
                //设置缓存最大容量为100，超过100之后就会按照LRU最近虽少使用算法来移除缓存项
                .maximumSize(100)
                //设置要统计缓存的命中率
                .recordStats()
                //设置缓存的移除通知
                .removalListener(new RemovalListener<Object, Object>() {
                    @Override
                    public void onRemoval(RemovalNotification<Object, Object> notification) {
                        System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
                    }
                })
				.build(new CacheLoader<String, String>(){

			@Override
			public String load(String key) throws Exception {
				System.out.println("loading service url cache ...");
				// TODO Auto-generated method stub
				String valString = null;
				MysqlDataSource ds = new MysqlDataSource();
				ds.setURL(getUrl("adhoc"));
				ds.setUser("root");
				ds.setPassword("admin_123");
				try(Connection conn = ds.getConnection();
						PreparedStatement statement = (PreparedStatement) conn
								.prepareStatement("SELECT * FROM adhoc_bu_serviceurl_mapping WHERE department = ?",
										ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) 
				{
					statement.setString(1, key);
					ResultSet resultSet = statement.executeQuery();
					resultSet.next();
					valString = resultSet.getString("service_url");
//					System.out.println(resultSet.getString("department") + " | " + resultSet.getString("service_url"));
				} catch (Exception e) {
					e.printStackTrace();
				}
				return valString;
			}
			
		});
		
		String department_name = "机票研发部";
		System.out.println("1 - " + loadingCache.get(department_name));
		System.out.println("2 - " + loadingCache.getIfPresent(department_name));
		TimeUnit.SECONDS.sleep(3);
		System.out.println("3 - after 6s - " + loadingCache.getIfPresent(department_name));
		System.out.println("4 - " + loadingCache.get(department_name));
		
		//休眠1秒
        System.out.println("cache stats:");
        //最后打印缓存的命中率等 情况
        System.out.println(loadingCache.stats().toString());
		
	}

	private String getUrl(String database) {
		return "jdbc:mysql://10.2.24.141:" + 3306 + "/" + database
				+ "?createDatabaseIfNotExist=false";
	}
}
